#ifndef MUTEX_H_
#define MUTEX_H_

#include <pthread.h>

namespace TP {    namespace Threading {

    class Mutex {
        private:
            pthread_mutex_t _mutex;
            pthread_cond_t _condVar;

        public:
            // Crea un mutex con atributos por default

            Mutex() {
                pthread_mutex_init(&_mutex, 0);
                pthread_cond_init(&_condVar, 0);
            }

            // Lock

            void lock() {
                pthread_mutex_lock(&_mutex);
            }

            // Unlock

            void unlock() {
                pthread_mutex_unlock(&_mutex);
            }

            // signal

            void signal() {
                pthread_cond_signal(&_condVar);
            }

            // wait

            void wait() {
                pthread_cond_wait(&_condVar, &_mutex);
            }

            // Destructor

            virtual ~Mutex() {
                pthread_mutex_destroy(&_mutex);
                pthread_cond_destroy(&_condVar);
            }

            friend class Lock;
        };

        // Patrón RAII para la clase mutex

        class Lock {
        private:
            Mutex &_mutex;

        public:
            // Construye un Lock bloqueando el mutex

            explicit Lock(Mutex &mutex) : _mutex(mutex) {
                _mutex.lock();
            }

            // Destruye el Lock desbloqueando el mutex

            ~Lock() {
                _mutex.unlock();
            }
        };
    }
}

#endif /* MUTEX_H_ */
